package com.elitel.frame.main.security;

import com.elitel.common.exception.TokenException;
import com.elitel.frame.base.service.UserInfoService;
import com.elitel.frame.main.entity.ext.ExtUserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;

/**
 * TODO: JwtTokenAuthorizationFilter
 *
 * @since 2020-02-20
 */
@Component
public class JwtTokenAuthorizationFilter extends OncePerRequestFilter {

  @Autowired private JwtTokenUtil jwtTokenUtil;
  @Autowired private UserInfoService userInfoService;

  @Override
  protected void doFilterInternal(
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse,
      FilterChain filterChain)
      throws ServletException, IOException {

//    HttpSession session = httpServletRequest.getSession(false);

    final String requestTokenHeader = httpServletRequest.getHeader("Authorization");

    // 判断 request 头部token授权是否存在
    if (requestTokenHeader == null || !requestTokenHeader.startsWith(jwtTokenUtil.getType())) {
      filterChain.doFilter(httpServletRequest, httpServletResponse);
      return;
    }

    // 获取 token
    String token = requestTokenHeader.substring(jwtTokenUtil.getType().length());
    try {
      Claims claimsFromToken = jwtTokenUtil.getClaimsFromToken(token);
      ExtUserInfo userInfo =
          userInfoService.selectByAuthorizationCode(claimsFromToken.getSubject());
      if (userInfo == null) {
        throw new TokenException("token 认证失败");
      } else {
        // 设置用户授权
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
            new UsernamePasswordAuthenticationToken(claimsFromToken.getSubject(), null, null);
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
      }

    } catch (ExpiredJwtException e) {
      throw new TokenException("token 已过期，请重新申请 " + e);
    }
    filterChain.doFilter(httpServletRequest, httpServletResponse);
  }
}
